/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-05-31     Dell       the first version
 */

#include "distance.h"


rt_device_t  hwtimer_device = RT_NULL;  // 定时器设备对象
static uint32_t time_count = 0;        // 定时器计数结果
static uint8_t send_trigger = 0;       // 是否已发送trigger


/**
 * 触发测距信号
 */
rt_err_t distance_detect(rt_device_t dev, rt_size_t size){
    if(send_trigger){
        if(rt_pin_read(DISTANCE_ECHO_PIN) == PIN_HIGH){
            time_count += 1;
        }
//        rt_kprintf("testing\n");
    }
    return RT_EOK;
}


/***
 * 定时查询距离
 */
void distance_timer_start(void *parameter){
    while(1){
        rt_thread_mdelay(2000);

        // 开启定时器计数
        rt_err_t res = rt_device_open(hwtimer_device, RT_DEVICE_OFLAG_RDWR);
        if(res != RT_EOK){
            rt_kprintf("open device %s failed\n", DISTANCE_HWTIM_DEVICE_NAME);
            return;
        }

        // 设置回调方法
        res = rt_device_set_rx_indicate(hwtimer_device, distance_detect);
        if(res != RT_EOK){
            rt_kprintf("rt_device_set_rx_indicate failed\n", DISTANCE_HWTIM_DEVICE_NAME);
            return;
        }

        // 设置计数频率
        rt_uint32_t freq = DISTANCE_DETECT_FREQ;
        res = rt_device_control(hwtimer_device, HWTIMER_CTRL_FREQ_SET, &freq);
        if(res != RT_EOK){
            rt_kprintf("rt_device_control HWTIMER_CTRL_FREQ_SET failed\n", DISTANCE_HWTIM_DEVICE_NAME);
            return;
        }

        rt_hwtimer_mode_t mode = HWTIMER_MODE_PERIOD;         /* 定时器模式 */
        res = rt_device_control(hwtimer_device, HWTIMER_CTRL_MODE_SET, &mode);
        if (res != RT_EOK)
        {
            rt_kprintf("set mode failed! ret is :%d\n", res);
            return;
        }

        send_trigger = 1;
        time_count = 0;

        /* 设置定时器超时值为5s并启动定时器 */
        rt_hwtimerval_t timeout_s;      /* 定时器超时值 */
        timeout_s.sec = 0;      /* 秒 */
        timeout_s.usec = 1000;     /* 微秒 */
        // TODO 1000微秒测出来最小的距离也有170cm，，误差很大，后续再了解一下STM32 硬件定时器的逻辑
        if (rt_device_write(hwtimer_device, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s))
        {
            rt_kprintf("set timeout value failed\n");
            return;
        }


        rt_pin_write(DISTANCE_TRIG_PIN, PIN_HIGH);
        rt_hw_us_delay(30);
        rt_pin_write(DISTANCE_TRIG_PIN, PIN_LOW);


        /* 延时500ms */
        rt_thread_mdelay(1000);

        // 停止定时器
        if(rt_device_control(hwtimer_device, HWTIMER_CTRL_STOP, RT_NULL) != RT_EOK){
            rt_kprintf("failed to stop hwtimer\n");
            return;
        }

        if(rt_device_close(hwtimer_device) != RT_EOK){
            rt_kprintf("failed to close hwtimer device\n");
            return;
        }

        /* 得出数量 */
        uint32_t real_distance = time_count * 170;
        rt_kprintf("real_distance = %d cm \n", real_distance);

        send_trigger = 0;


    }
    return;
}

/***
 * 初始化测距模块
 */
void distance_init(){

    /* 获取定时器设备 */
    rt_device_t device = rt_device_find(DISTANCE_HWTIM_DEVICE_NAME);
    if(device == RT_NULL){
        rt_kprintf("can not find device %s\n", DISTANCE_HWTIM_DEVICE_NAME);
        return;
    }
    hwtimer_device = device;

    /* 设置输出模式 */
    rt_pin_mode(DISTANCE_TRIG_PIN, PIN_MODE_OUTPUT);
    rt_pin_write(DISTANCE_TRIG_PIN, PIN_LOW);

    /* 开启定时器，定时测距 */
    rt_thread_t distance_thread = rt_thread_create("distance_timer_start", distance_timer_start, RT_NULL, 512, 10, 10);
    if(distance_thread == RT_NULL){
        rt_kprintf("distance detect failed to create thread!\n");
        return;
    }
    rt_err_t res = rt_thread_startup(distance_thread);
    if(res != RT_EOK){
        rt_kprintf("distance detect failed to start thread!\n");
        return;
    }
    return;

}
